/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef MC_TEST_HI182X_COMMON_H
#define MC_TEST_HI182X_COMMON_H

#include <devmon/driver_abi.h>
#include <dlfcn.h>
#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include <mc/common.h>
#include <ncsi/ncsi_socket.h>
#include <ncsi/ncsi_protocol.h>
#include <ncsi/ncsi_huawei.h>
#include <ncsi_over_mctp/ncsi_over_mctp_huawei.h>

#include "hi182x/hi182x_card.h"
#include "hi182x/hi182x_om.h"
#include "hi182x/hi182x_port.h"

using namespace dev;

namespace drivers {
namespace pcie_nic_card {
namespace hisi {
namespace test {

// 测试服务类
class hi182x_test_service : public mc::engine::service {
public:
    hi182x_test_service(const std::string& name) : mc::engine::service(name) {}
};

// 公共测试基类
class Hi182xAbiTest : public mc::test::TestWithEngine {
public:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service.init();
        m_test_service.start();
        load_driver();
    }

    static void TearDownTestSuite() {
        m_test_service.stop();
        if (m_driver_handle != nullptr) {
            dlclose(m_driver_handle);
            m_driver_handle = nullptr;
        }
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {}

    void TearDown() override {}

    static void load_driver() {
        m_driver_handle = dlopen("./opt/bmc/drivers/libhisi_182x.so", RTLD_LAZY);
        if (m_driver_handle == nullptr) {
            MC_THROW(mc::system_exception, "Failed to load driver: ${error}", ("error", dlerror()));
        }
        register_device_driver_func func = reinterpret_cast<register_device_driver_func>(
            dlsym(m_driver_handle, "register_device_driver"));
        MC_ASSERT_THROW(func, mc::bad_function_call_exception,
                        "Failed to get export_device_driver function: ${error}",
                        ("error", dlerror()));

        device_driver_t* devices       = nullptr;
        uint8_t          devices_count = 0;
        status_t         ret           = func(&devices, &devices_count);
        MC_ASSERT_THROW(ret == STATUS_OK, mc::bad_function_call_exception,
                        "Failed to get device driver manager: ${error}", ("error", ret));

        m_devices.clear();
        m_devices.reserve(devices_count);
        for (uint8_t i = 0; i < devices_count; i++) {
            auto device_driver = std::make_shared<device_driver_t>(devices[i]);
            m_devices.emplace(device_driver->device_name, device_driver);
        }
    }

    mc::dict create_test_connector(uint8_t system_id, uint8_t position, uint8_t slot) {
        return mc::dict{{"SystemId", system_id}, {"Position", position}, {"Slot", slot}};
    }

    static hi182x_test_service                                               m_test_service;
    static std::unordered_map<std::string, std::shared_ptr<device_driver_t>> m_devices;
    static void*                                                             m_driver_handle;
};

// 静态成员初始化
inline hi182x_test_service Hi182xAbiTest::m_test_service{"bmc.kepler.test_hi182x"};
inline std::unordered_map<std::string, std::shared_ptr<device_driver_t>> Hi182xAbiTest::m_devices;
inline void* Hi182xAbiTest::m_driver_handle = nullptr;

} // namespace test
} // namespace hisi
} // namespace pcie_nic_card
} // namespace drivers

#endif // MC_TEST_HI182X_COMMON_H

